#define DEBUG
#include <cstdio>

using namespace std;

const int maxn=50000, maxm=2*maxn;

int min(int a, int b) {
  return a<b ? a : b;
}

int max(int a, int b) {
  return a>b ? a : b;
}

class Tree {
public:
  int n, m, fa[2*maxn+1], son[2*maxn+1], bro[2*maxn+1], f[2*maxn+1], val[2*maxn+1];
  bool squ[2*maxn+1];

  void addSide(int f, int s, int w) {
    fa[s] = f;
    val[s] = w;
    bro[s] = son[f];
    son[f] = s;
  }

  int solveSqu(int o) {
    static int q[maxn+1][2], v[maxn+1];
    int n=1, ret=0;
    v[1] = 0;
    for (int i=son[o]; i; i=bro[i]) {
      v[++n] = f[i];
    }
    for (int i=n+1; i<=2*n; i++) {
      v[i] = v[i-n];
    }

    int h=1, t=1;
    q[1][0]=1, q[1][1]=-1;
    for (int i=2; i<=2*n; i++) {
      for (; h<=t && q[h][0]<i-n/2; h++);
      if (h<=t) ret = max(ret, v[i]+q[h][1]+i);
      int temp=v[i]-i;
      for (; h<=t && q[t][1]<=temp; t--);
      q[++t][0] = i;
      q[t][1] = temp;
    }
    return ret;
  }

  int solve(int o) {
    int sv=0, ret=0;
    for (int i=son[o]; i; i=bro[i]) {
      ret = max(ret, solve(i));
      if (f[i]+val[i]>=f[o]) {
        sv = f[o];
        f[o] = f[i]+val[i];
      } else if (f[i]+val[i]>=sv) {
        sv = f[i]+val[i];
      }
    }
    
    if (squ[o]) {
      return max(ret, solveSqu(o));
    } else {
      return max(ret, f[o]+sv);
    }
  }
};


class Graph {
public:
  int n, m=1, ind[maxn+2], to[2*maxm+2], link[2*maxm+2], low[maxn+1], dfn[maxn+1];
  bool book[2*maxm+2];

  void addSide(int u, int v) {
    m++;
    to[m] = v;
    link[m] = ind[u];
    ind[u] = m;
  }

  void buildTree(Tree &t, int o, int fa) {
    static int s[maxn+1];
    s[++s[0]] = o;
    low[o] = dfn[o] = ++dfn[0];
    for (int i=ind[o]; i; i=link[i]) {
      if (!book[i]) {
        if (!dfn[to[i]]) {
          book[i] = book[i^1] = true;
          buildTree(t, to[i], o);
          low[o] = min(low[o], low[to[i]]);
        } else {
          low[o] = min(low[o], dfn[to[i]]);
        }
      }
    }

    if (low[o]>=dfn[fa]) {
      int tar=o;
      if (s[s[0]]!=o) {
        int size=1, i;
        for (; s[s[0]-size+1]!=o; size++);
        size++;

        tar = ++t.n;
        t.squ[tar]=true;
        for (i=1; s[0] && s[s[0]]!=o; s[0]--, i++) {
          t.addSide(t.n, s[s[0]], min(i, size-i));
        }
        t.addSide(t.n, o, min(i, size-i));
      }
      s[0]--;
      t.addSide(fa, tar, tar==o);
    }
  }
};

int main() {
#ifdef DEBUG
  freopen("src.in", "r", stdin);
  freopen("src.out", "w", stdout);
#endif

  static Graph g;
  static Tree t;
  int n, m;
  scanf("%d %d", &n, &m);
  t.n = g.n = n;
  for (int i=1; i<=m; i++) {
    int k, u, v;
    scanf("%d %d", &k, &u);
    for (int j=2; j<=k; j++) {
      scanf("%d", &v);
      if (u!=v) {
        g.addSide(u, v);
        g.addSide(v, u);
        u = v;
      }
    }
  }

  g.buildTree(t, 1, 0);
  printf("%d", t.solve(1));

  fclose(stdin);
  fclose(stdout);
  return 0;
}
